<template>
  <div class="container">
    <!-- 图片容器 -->
    <div
      ref="imgContainer"
      class="image-container"
      :class="{ drawing: isCreatingCrop, moving: draggingCrop }"
      @wheel.prevent="handleWheel"
      @mousedown="startCrop"
      @mousemove="dragCrop"
      @mouseup="endCrop"
    >
      <img class="imgEl" ref="imgEl" :src="curNodeImgUrl" :style="imgStyle" @load="initImage" />
      <!-- 裁剪框 -->
      <VueDraggableResizable
        v-if="cropVisible"
        v-model:x="crop.x"
        v-model:y="crop.y"
        v-model:w="crop.w"
        v-model:h="crop.h"
        :parent="true"
        :aspectRatio="!isCreatingCrop"
        :resizable="true"
        :draggable="true"
        @dragging="updateCoordinates"
        @resizing="updateCoordinates"
        @drag-start="handleDragStart"
        @drag-end="handleDragEnd"
        class="crop-box"
      />
    </div>
    <el-drawer v-model="drawer" :with-header="false">
      <img v-if="resultImg" :src="resultImg" />
    </el-drawer>
  </div>
</template>

<script setup>
import { ref, computed, onMounted, onUnmounted } from "vue";
import VueDraggableResizable from "vue3-draggable-resizable";
import imageSrc from "@/assets/test/2.jpg";
const imgEl = ref(null);
const imgContainer = ref(null);
const resultImg = ref("");

const cropVisible = ref(false); // 裁剪框是否可见
const isCreatingCrop = ref(false); // 是否正在绘制裁剪框
const cropStart = ref({ x: 0, y: 0 }); // 鼠标按下起点
const draggingCrop = ref(false);
const isDraggingCrop = ref(false);

const drawer = ref(false);

const state = ref({
  scale: 1, // 缩放比例
  offsetX: 0, // 偏移X
  offsetY: 0, // 偏移Y
  naturalWidth: 0, // 原始宽度
  naturalHeight: 0 // 原始高度
}); // 裁剪区域

const crop = ref({
  x: 100,
  y: 100,
  w: 200,
  h: 200
}); // 拖拽开始

const props = defineProps({
  curNodeImgUrl: {
    type: String,
    default: ""
  }
});

// 计算图片的CSS变换样式
const imgStyle = computed(() => ({
  transform: `translate(${state.value.offsetX}px, ${state.value.offsetY}px) scale(${state.value.scale})`,
  transformOrigin: "0 0"
}));

// 初始化图片参数
const initImage = () => {
  state.value.naturalWidth = imgEl.value.naturalWidth;
  state.value.naturalHeight = imgEl.value.naturalHeight;
};

// **核心转换函数**
const viewportToImageCoordinates = (x, y) => {
  return {
    x: (x - state.value.offsetX) / state.value.scale,
    y: (y - state.value.offsetY) / state.value.scale
  };
};

// 计算鼠标相对图片的坐标
const getMousePosRelativeToImage = event => {
  const rect = imgEl.value.getBoundingClientRect();
  return {
    x: event.clientX - rect.left,
    y: event.clientY - rect.top
  };
};

const startCrop = e => {
  // 只在点击图片本身时开始新建裁剪框，避免点击裁剪框时也触发
  // if (e.target !== imgEl.value) return;
  const target = e.target;
  if (target.closest(".crop-box")) return; // 👈 点击裁剪框则不进入绘制逻辑

  const rect = imgContainer.value.getBoundingClientRect();
  const startX = e.clientX - rect.left;
  const startY = e.clientY - rect.top;

  cropStart.value = { x: startX, y: startY };
  crop.value.x = startX;
  crop.value.y = startY;
  crop.value.w = 0;
  crop.value.h = 0;

  isCreatingCrop.value = true;
  cropVisible.value = true;
};

const dragCrop = e => {
  if (!isCreatingCrop.value) return;

  const rect = imgContainer.value.getBoundingClientRect();
  const currentX = e.clientX - rect.left;
  const currentY = e.clientY - rect.top;

  const dx = currentX - cropStart.value.x;
  const dy = currentY - cropStart.value.y;

  crop.value.x = dx < 0 ? currentX : cropStart.value.x;
  crop.value.y = dy < 0 ? currentY : cropStart.value.y;
  crop.value.w = Math.abs(dx);
  crop.value.h = Math.abs(dy);
};

const endCrop = () => {
  if (isCreatingCrop.value) {
    isCreatingCrop.value = false;
    updateCoordinates(); // 更新真实坐标
    setTimeout(() => {
      drawer.value = true;
      doCrop();
    }, 10);
  }
};

const handleDragStart = () => {
  isDraggingCrop.value = true;
  document.body.style.userSelect = "none";
  document.body.style.cursor = "move"; // 强制鼠标为 move
};

const handleDragEnd = () => {
  isDraggingCrop.value = false;
  document.body.style.userSelect = "";
  document.body.style.cursor = ""; // 恢复默认
};

// 滚轮缩放（优化版）
const handleWheel = e => {
  e.preventDefault(); // 计算缩放比例
  const delta = e.deltaY > 0 ? 0.9 : 1.1;
  const newScale = Math.max(0.01, state.value.scale * delta); // 计算鼠标在图片中的相对位置

  const rect = imgContainer.value.getBoundingClientRect();
  const mouseX = e.clientX - rect.left; // 鼠标在容器中的 X 坐标
  const mouseY = e.clientY - rect.top; // 鼠标在容器中的 Y 坐标 // 计算鼠标相对图片的坐标

  const imgMouseX = (mouseX - state.value.offsetX) / state.value.scale;
  const imgMouseY = (mouseY - state.value.offsetY) / state.value.scale; // 计算新的偏移，使鼠标位置不变

  state.value.offsetX = mouseX - imgMouseX * newScale;
  state.value.offsetY = mouseY - imgMouseY * newScale; // 更新缩放

  state.value.scale = newScale;
};

// 更新裁剪坐标（修正缩放导致的偏移问题）
const updateCoordinates = () => {
  draggingCrop.value = true;
  requestAnimationFrame(() => {
    draggingCrop.value = false;
  });

  const start = viewportToImageCoordinates(crop.value.x, crop.value.y);
  const end = viewportToImageCoordinates(crop.value.x + crop.value.w, crop.value.y + crop.value.h); // 确保裁剪区域不会超出图片边界
  crop.value.realX = Math.max(0, Math.min(start.x, state.value.naturalWidth));
  crop.value.realY = Math.max(0, Math.min(start.y, state.value.naturalHeight));
  crop.value.realW = Math.min(end.x - start.x, state.value.naturalWidth - start.x);
  crop.value.realH = Math.min(end.y - start.y, state.value.naturalHeight - start.y);
};

// **执行裁剪**
const doCrop = () => {
  const canvas = document.createElement("canvas");
  const ctx = canvas.getContext("2d"); // 设置裁剪区域的尺寸

  canvas.width = crop.value.realW;
  canvas.height = crop.value.realH; // 这里去掉 `state.value.scale`，因为 `realX` 和 `realY` 已经是原始图片坐标

  ctx.drawImage(
    imgEl.value,
    crop.value.realX, // 去掉 state.value.scale
    crop.value.realY, // 去掉 state.value.scale
    crop.value.realW, // 去掉 state.value.scale
    crop.value.realH, // 去掉 state.value.scale
    0,
    0,
    crop.value.realW,
    crop.value.realH
  );

  resultImg.value = canvas.toDataURL("image/png");
};
</script>
<style>
.container {
  position: relative;
  width: 100%;
  height: 100%;
  border: 1px solid #cccccc;

  /* overflow: hidden; */
}
.image-container {
  position: relative;
  width: 100%;
  height: 100%;
  overflow: hidden;
  background-color: #f0f0f0; /* 使整体背景更浅 */
  background-image: linear-gradient(45deg, #dddddd 25%, transparent 25%), linear-gradient(-45deg, #dddddd 25%, transparent 25%),
    linear-gradient(45deg, transparent 75%, #dddddd 75%), linear-gradient(-45deg, transparent 75%, #dddddd 75%);
  background-position: 0 0, 0 6px, 6px -6px, -6px 0; /* 适配新的大小 */
  background-size: 12px 12px; /* 让格子更小 */
}
.image-container.drawing {
  cursor: crosshair;
}
.image-container.moving {
  cursor: move;
}
.imgEl {
  position: absolute;

  /* cursor: move; */
  user-select: none;
}
.crop-box {
  background: rgb(255 0 0 / 20%);
  border: 2px dashed red;
}
</style>
